﻿using Engine;
using Game;
using System;

namespace SAGhoul
{
	public class SAGProjectile : Projectile
	{
		public ComponentCreature Target
		{
			get; set;
		}
		public bool LockNearestPlayerIfNoTarget
		{
			get; set;
		} = true;
		readonly Game.Random m_random = new();
		float? timeToRemove;
		public override void UpdateMovement(float dt, ref Vector3 positionAtdt)
		{
			if (Target != null && Target.IsAddedToProject && Target.ComponentHealth.Health > 0f)
			{
				Gravity = 0f;
				IsFireProof = true;
				Vector3 v2 = Target.ComponentBody.BoundingBox.Center() - Position;
				float num7 = v2.LengthSquared();
				float nearRange = Target is ComponentPlayer ? 3f : 0.5f;//进入近距离后不再追踪。越小锁的越死
				if (num7 >= MathUtils.Sqr(nearRange))
				{
					Velocity = 4.5f * v2 / MathF.Sqrt(num7);
				}
				else
				{
					LockNearestPlayerIfNoTarget = false;
					Target = null;
				}
			}
			else if (LockNearestPlayerIfNoTarget && SubsystemProjectiles != null)
			{//没有目标时锁定最近的玩家
				var players = SubsystemProjectiles.Project.FindSubsystem<SubsystemPlayers>().ComponentPlayers;
				if (players.Count == 1)
					Target = players[0];
				else
				{
					ComponentPlayer nearestPlayer = null;
					float nearestDistanceSquared = float.MaxValue;
					foreach (var player in players)
					{
						if (player.ComponentHealth.Health > 0f)
						{
							float distanceSquared = Vector3.DistanceSquared(player.ComponentBody.BoundingBox.Center(), Position);
							if (distanceSquared < nearestDistanceSquared)
							{
								nearestDistanceSquared = distanceSquared;
								nearestPlayer = player;
							}
						}
					}
					if (nearestPlayer != null)
						Target = nearestPlayer;
				}
			}
			else if (Velocity.Y > 0f)//已丢锁且正在往天上飞，下坠使其摔碎避免乱飞
				Gravity = 10f;
			else if (!timeToRemove.HasValue)
				timeToRemove = 5f;
			Block block = BlocksManager.Blocks[Terrain.ExtractContents(Value)];
			if (Damping < 0f)
			{
				Damping = block.GetProjectileDamping(Value);
			}
			float friction = IsInFluid ? MathF.Pow(DampingInFluid, dt) : MathF.Pow(Damping, dt);
			Velocity.Y += -Gravity * dt;
			Velocity *= friction;
			AngularVelocity *= friction;
			Position = positionAtdt;
			Rotation += AngularVelocity * dt;
			int cellContents = CurrnetTerrain().GetCellContents(Terrain.ToCell(Position.X), Terrain.ToCell(Position.Y), Terrain.ToCell(Position.Z));
			Block blockTheProjectileIn = BlocksManager.Blocks[cellContents];
			bool isProjectileInFluid = false;// blockTheProjectileIn is FluidBlock;
			if (TrailParticleSystem != null)
			{
				UpdateTrailParticleSystem(dt);
			}
			if (isProjectileInFluid && !IsInFluid)
			{
				if (DampingInFluid <= 0.001f)
				{
					float horizontalSpeed = new Vector2(Velocity.X + Velocity.Z).Length();
					if (horizontalSpeed > 6f
						&& horizontalSpeed > 4f * MathF.Abs(Velocity.Y))
					{
						Velocity *= 0.5f;
						Velocity.Y *= -1f;
						isProjectileInFluid = false;
					}
					else
					{
						Velocity *= 0.2f;
					}
				}
				float? surfaceHeight = SubsystemProjectiles?.m_subsystemFluidBlockBehavior.GetSurfaceHeight(
					Terrain.ToCell(Position.X),
					Terrain.ToCell(Position.Y),
					Terrain.ToCell(Position.Z)
				);
				if (surfaceHeight.HasValue
					&& SubsystemParticles != null
					&& SubsystemAudio != null)
				{
					if (blockTheProjectileIn is MagmaBlock)
					{
						SubsystemParticles.AddParticleSystem(new MagmaSplashParticleSystem(SubsystemTerrain, Position, false));
						SubsystemAudio.PlayRandomSound("Audio/Sizzles", 1f, m_random.Float(-0.2f, 0.2f), Position, 3f, true);
						if (!IsFireProof)
						{
							ToRemove = true;
							SubsystemProjectiles?.m_subsystemExplosions.TryExplodeBlock(
								Terrain.ToCell(Position.X),
								Terrain.ToCell(Position.Y),
								Terrain.ToCell(Position.Z),
								Value
							);
						}
					}
					else
					{
						SubsystemParticles.AddParticleSystem(
							new WaterSplashParticleSystem(SubsystemTerrain, new Vector3(Position.X, surfaceHeight.Value, Position.Z), false)
						);
						SubsystemAudio.PlayRandomSound("Audio/Splashes", 1f, m_random.Float(-0.2f, 0.2f), Position, 6f, true);
					}
					MakeNoise();
				}
			}
			IsInFluid = isProjectileInFluid;
			if (SubsystemProjectiles != null
				&& SubsystemAudio != null)
			{
				if (!IsFireProof
					&& SubsystemProjectiles.m_subsystemTime.PeriodicGameTimeEvent(1.0, GetHashCode() % 100 / 100.0)
					&& (SubsystemProjectiles.m_subsystemFireBlockBehavior.IsCellOnFire(
							Terrain.ToCell(Position.X),
							Terrain.ToCell(Position.Y + 0.1f),
							Terrain.ToCell(Position.Z)
						)
						|| SubsystemProjectiles.m_subsystemFireBlockBehavior.IsCellOnFire(
							Terrain.ToCell(Position.X),
							Terrain.ToCell(Position.Y + 0.1f) - 1,
							Terrain.ToCell(Position.Z)
						)))
				{
					SubsystemAudio.PlayRandomSound("Audio/Sizzles", 1f, m_random.Float(-0.2f, 0.2f), Position, 3f, true);
					ToRemove = true;
					SubsystemProjectiles.m_subsystemExplosions.TryExplodeBlock(
						Terrain.ToCell(Position.X),
						Terrain.ToCell(Position.Y),
						Terrain.ToCell(Position.Z),
						Value
					);
				}
			}
			if (timeToRemove.HasValue)
			{
				timeToRemove -= dt;
				if (timeToRemove < 0)
					ToRemove = true;
			}
		}

	}
}
